#Review of comprehensions
l = [i * 2 for i in range(10)]
l
type(l)

d = {i: i * 2 for i in range(10)} 
type(d)
s = {i for i in range(10)} 
type(s) 
g = (i for i in range(10))
type(g)


#Multi-input comprehensions
[(x, y) for x in range(5) for y in range(3)] 


#Equivalence with nested for-loops
points = [] 
for x in range(5): 
	for y in range(3): 
		points.append((x, y))

points


#Multiple if-clauses
values = [x / (x - y) for x in range(100) if x > 50 for y in range(100) if x - y != 0]
values

values = [x / (x - y) 
	  for x in range(100) 
          	if x > 50 
          for y in range(100) 
		if x - y != 0]
values

values = [] 
for x in range(100): 
	if x > 50: 
		for y in range(100): 
			if x - y != 0: 
				values.append(x / (x - y))
values


#Looping variable binding
[(x, y) for x in range(10) for y in range(x)] 

result = [] 
for x in range(10): 
	for y in range(x): 
		result.append((x, y))

result


#Nested comprehensions
vals = [[y * 3 for y in range(x)] for x in range(10)]
vals

outer = [] 
for x in range(10): 
	inner = [] 
	for y in range(x): 
		inner.append(y * 3) 
	outer.append(inner)

outer


#Generator expressions, set comprehensions,and dictionary comprehensions
{x * y for x in range(10) for y in range(10)}

g = ((x, y) for x in range(10) for y in range(x))
type(g) 
list(g) 